package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.OrdersConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.properties.BaiduMapProperties;
import com.sky.properties.WeChatProperties;
import com.sky.result.PageResult;
import com.sky.service.OrdersService;
import com.sky.utils.BaiduMapUtil;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrdersServiceImpl implements OrdersService {
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrdersDetailMapper ordersDetailMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private WeChatPayUtil weChatPayUtil;
    @Autowired
    private BaiduMapProperties baiduMapProperties;
    @Autowired
    private BaiduMapUtil baiduMapUtil;
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 取消订单
     *
     * @param dto
     */
    @Override
    public void cancelOrders(OrdersCancelDTO dto) {
        Orders orders = Orders.builder()
                .cancelReason(dto.getCancelReason())
                .cancelTime(LocalDateTime.now())
                .status(Orders.CANCELLED)
                .id(dto.getId())
                .payStatus(Orders.REFUND)
                .build();
        ordersMapper.update(orders);
    }

    /**
     * 用户下单
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public OrderSubmitVO submit(OrdersSubmitDTO dto) {
        //补充订单对象信息
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto,orders);
        orders.setNumber(System.currentTimeMillis()+"");
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setUserId(BaseContext.getCurrentId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        //获取手机号,地址，用户名，收货人
        //获取地址
        AddressBook addressBook = addressBookMapper.getById(orders.getAddressBookId());
        if(addressBook == null){
            throw new  OrderBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        try {
            if (!baiduMapUtil.checkDistance(addressBook.getProvinceName()+addressBook.getCityName()+addressBook.getDistrictName()+addressBook.getDetail(), baiduMapProperties.getAddress())){
                throw new AddressBookBusinessException("超出配送范围");
            }
        } catch (Exception e) {
            throw new AddressBookBusinessException("超出配送范围");
        }
        orders.setPhone(addressBook.getPhone());
        orders.setAddress(addressBook.getDetail());
        orders.setConsignee(addressBook.getConsignee());
        //获取用户
        User user = userMapper.getById(orders.getUserId());
        orders.setUserName(user.getName());
        //提交订单对象
        ordersMapper.submit(orders);
        //补充订单细节对象信息
        List<OrderDetail> orderDetails = new ArrayList<>();
        //获取用户购物车
        ShoppingCart shoppingCart = ShoppingCart.builder().userId(BaseContext.getCurrentId()).build();
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.getBy(shoppingCart);
        for (ShoppingCart cart : shoppingCarts) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(cart,orderDetail,"id");
            orderDetail.setOrderId(orders.getId());
            orderDetails.add(orderDetail);
        }
        //提交订单细节对象
        ordersDetailMapper.submit(orderDetails);
        //删除购物车
        shoppingCartMapper.delete(shoppingCart);
        //生成返回值vo
        return new OrderSubmitVO(orders.getId(),orders.getNumber(),orders.getAmount(),orders.getOrderTime());
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        /*// 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getById(userId);

        //调用微信支付接口，生成预支付交易单
        JSONObject jsonObject = weChatPayUtil.pay(
                ordersPaymentDTO.getOrderNumber(), //商户订单号
                new BigDecimal(0.01), //支付金额，单位 元
                "苍穹外卖订单", //商品描述
                user.getOpenid() //微信用户的openid
        );

        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
            throw new OrderBusinessException("该订单已支付");
        }

        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));*/

        paySuccess(ordersPaymentDTO.getOrderNumber());
        OrderPaymentVO vo = new OrderPaymentVO();
        return vo;
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    public void paySuccess(String outTradeNo) {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单号查询当前用户的订单
        Orders ordersDB = ordersMapper.getByNumberAndUserId(outTradeNo, userId);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        ordersMapper.update(orders);

        // 来单提醒
        Map map = new HashMap();
        map.put("type", OrdersConstant.CALL_REMINDER);
        map.put("orderId",ordersDB.getId());
        map.put("content","订单号："+ordersDB.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }

    /**
     * 历史订单查询
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult getHistory(OrdersPageQueryDTO dto) {
        dto.setUserId(BaseContext.getCurrentId());
        PageHelper.startPage(dto.getPage(),dto.getPageSize());
        Page<OrderVO> vos = ordersMapper.getBy(dto);
        for (OrderVO vo : vos) {
            List<OrderDetail> details = ordersDetailMapper.getByOrder(vo.getId());
            if(!details.isEmpty()){
                vo.setOrderDetailList(details);
            }
            /*if(vo.getStatus().equals(Orders.PENDING_PAYMENT)){
                LocalDateTime orderTime = vo.getOrderTime();
                LocalDateTime now = LocalDateTime.now();
                long minutes = Duration.between(orderTime, now).toMinutes();
                if(minutes>=15){
                    Orders orders = new Orders();
                    vo.setStatus(Orders.CANCELLED);
                    vo.setCancelTime(orderTime.plusMinutes(15));
                    vo.setCancelReason("用户未按时支付已自动取消");
                    BeanUtils.copyProperties(vo,orders);
                    ordersMapper.update(orders);
                }
            }*/
        }
        return new PageResult(vos.getTotal(),vos.getResult());
    }

    /**
     * 查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderVO getOrder(Long id) {
        Orders orders = Orders.builder().id(id).build();
        orders = ordersMapper.getByOrder(orders);
        OrderVO vo = new OrderVO();
        BeanUtils.copyProperties(orders,vo);
        List<OrderDetail> details = ordersDetailMapper.getByOrder(vo.getId());
        vo.setOrderDetailList(details);
        return vo;
    }

    /**
     * 取消订单
     *
     * @param id
     */
    @Override
    public void cancelOrder(Long id) {
        Orders orders = Orders.builder().id(id).build();
        orders = ordersMapper.getByOrder(orders);
        orders.setCancelReason("用户取消订单");
        orders.setCancelTime(LocalDateTime.now());
        if(orders.getStatus().equals(Orders.PENDING_PAYMENT)){
            orders.setStatus(Orders.CANCELLED);
        }else {
            orders.setStatus(Orders.CANCELLED);
            orders.setPayStatus(Orders.REFUND);
        }
        ordersMapper.update(orders);
    }

    /**
     * 再来一单
     *
     * @param id
     */
    @Override
    public void oneMoreOrder(Long id) {
        List<OrderDetail> details = ordersDetailMapper.getByOrder(id);
        for (OrderDetail detail : details) {
            ShoppingCart shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(detail,shoppingCart,"id");
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCartMapper.add(shoppingCart);
        }
    }

    /**
     * 订单搜索
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult searchOrder(OrdersPageQueryDTO dto) {
        PageHelper.startPage(dto.getPage(),dto.getPageSize());
        Page<OrderVO> vos = ordersMapper.getBy(dto);
        for (OrderVO vo : vos) {
            List<OrderDetail> details = ordersDetailMapper.getByOrder(vo.getId());
            List<String> dishes = details.stream().map(detail -> detail.getName() + "*" + detail.getNumber()).collect(Collectors.toList());
            String dishesS = dishes.toString();
            vo.setOrderDishes(dishesS.substring(1,dishesS.length()-1));
        }
        return new PageResult(vos.getTotal(),vos.getResult());
    }

    /**
     * 各个状态的订单数量统计
     *
     * @return
     */
    @Override
    public OrderStatisticsVO getStatistics() {
        OrderStatisticsVO vo = new OrderStatisticsVO();
        vo.setToBeConfirmed(ordersMapper.getStatistics(Orders.TO_BE_CONFIRMED));
        vo.setConfirmed(ordersMapper.getStatistics(Orders.CONFIRMED));
        vo.setDeliveryInProgress(ordersMapper.getStatistics(Orders.DELIVERY_IN_PROGRESS));
        return vo;
    }

    /**
     * 接单
     *
     * @param dto
     */
    @Override
    public void confirm(OrdersConfirmDTO dto) {
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto,orders);
        orders.setStatus(Orders.CONFIRMED);
        ordersMapper.update(orders);
    }

    /**
     * 拒单
     *
     * @param dto
     */
    @Override
    public void rejection(OrdersRejectionDTO dto) {
        Orders orders = new Orders();
        BeanUtils.copyProperties(dto,orders);
        orders.setStatus(Orders.CANCELLED);
        orders.setPayStatus(Orders.REFUND);
        orders.setCancelTime(LocalDateTime.now());
        orders.setCancelReason(orders.getRejectionReason());
        ordersMapper.update(orders);
    }

    /**
     * 派送订单
     *
     * @param id
     */
    @Override
    public void delivery(Long id) {
        Orders orders = Orders.builder()
                .id(id)
                .status(Orders.DELIVERY_IN_PROGRESS)
                .build();
        ordersMapper.update(orders);
    }

    /**
     * 完成订单
     *
     * @param id
     */
    @Override
    public void complete(Long id) {
        Orders orders = Orders.builder()
                .id(id)
                .status(Orders.COMPLETED)
                .deliveryTime(LocalDateTime.now())
                .build();
        ordersMapper.update(orders);
    }

    /**
     * 催单
     *
     * @param id
     */
    @Override
    public void reminder(Long id) {
        Orders orders = Orders.builder().id(id).build();
        orders = ordersMapper.getByOrder(orders);
        Map message = new HashMap();
        message.put("type",OrdersConstant.CUSTOMER_REMINDER);
        message.put("orderId",orders.getId());
        message.put("content","订单号："+orders.getNumber());
        webSocketServer.sendToAllClient(JSON.toJSONString(message));
    }
}
